#pragma once

#include "NodoSimple.h"
#include <iostream>
#include <string>
#include <sstream>
using namespace std;

template <class T>
class ListaEnlazada
{
private:
    
    NodoSimple<T>* primero;  //puntero al inicio
	NodoSimple<T>* actual;
	int cantidad;
	string flag;
public: 
	ListaEnlazada();
	ListaEnlazada(ListaEnlazada *);  //constructor copia
	virtual ~ListaEnlazada();

	string getFlag();
	void setFlag(string);
	NodoSimple<T>* getPrimero();
	NodoSimple<T>* getActual();
	void setActual(NodoSimple<T> *);
    void setPrimero(NodoSimple<T> *);
	void insertarUltimo(T*);
	void insertarPrimero(T *);
    void insertarPos(int pos, T*e);
    void eliminarPos(int pos);
    void intercambiar(int posA, int posB);
	//virtual int eliminar(string);		
	string toString();
	T * buscar(string);
	int getCantidad();
	void setCantidad(int);
};


template<class T>
string ListaEnlazada<T>::getFlag(){
   return flag;
}

template<class T>
void ListaEnlazada<T>::setFlag(string a){
	flag = a;
}


template<class T>
NodoSimple<T>* ListaEnlazada<T>::getActual(){
   return actual;


}



template<class T>
NodoSimple<T>* ListaEnlazada<T>::getPrimero(){
   return primero;


}

template<class T>
void ListaEnlazada<T>::setActual(NodoSimple<T> *act){

actual=act;

}

template<class T>
void ListaEnlazada<T>::setCantidad(int c){

cantidad = c;

}

template<class T>
void ListaEnlazada<T>::setPrimero(NodoSimple<T> *prim){

primero=prim;

}





template<class T>
ListaEnlazada<T>::ListaEnlazada()
{
	actual = primero = NULL; 
	cantidad = 0;
}

template<class T>
ListaEnlazada<T>::ListaEnlazada(ListaEnlazada<T> *list)
{   
	
	list->setActual(list->getPrimero());
	while(list->getActual() != NULL)
	{
		insertarPrimero(new T(list->getActual()->getInfo()));
		list->setActual(list->getActual()->getSigNodo());
	}
}


template<class T>
ListaEnlazada<T>::~ListaEnlazada()
{
	while(primero!=NULL)
	{
		actual = primero;
	    primero=primero->getSigNodo();
	    delete actual;
	}

}

template<class T>
void ListaEnlazada<T>::insertarPrimero(T * c)
{
	if(primero == NULL)
	{
		primero = new NodoSimple<T>(NULL,c);
	}
	else
	{
		actual = new NodoSimple<T>(primero,c);
		primero = actual;
	}
	cantidad++;
}

template<class T>
void ListaEnlazada<T>::insertarUltimo(T * c)
{
	if(primero == NULL)
	{
		primero = new NodoSimple<T>(NULL,c);
	}
	else
	{
		NodoSimple<T>* ant;
		actual = primero;
		while(actual != NULL)
		{
			ant = actual;
			actual = actual->getSigNodo();
		}
		actual = new NodoSimple<T>(NULL,c);
		ant->setSigNodo(actual);
	}
	cantidad++;
}
/*Se ocupan sobrecargas
template<class T>
int ListaEnlazada<T>::eliminar(string codigo){
	
	int ret = 0;
	if(primero!=NULL)
	{
	    actual = primero;
		if(*(primero->getInfo())== codigo)
		{
			primero=primero->getSigNodo();
			delete actual;
			cantidad--;
		}
		else
		{

			NodoSimple<T> *aux;
			while(actual->getSigNodo()!=NULL)
			{   
				if(*(actual->getSigNodo()->getInfo())==codigo)
				{
					aux=actual->getSigNodo();
					actual->setSigNodo(actual->getSigNodo()->getSigNodo());
					delete aux;
					cantidad--;
					ret = 1;
				}
				actual=actual->getSigNodo();
			}
		}
	}
	return ret;
}
*/
template<class T>
string ListaEnlazada<T>::toString()
{
	stringstream s; 
    if(primero==NULL)
    	s<<"\t\tLa lista esta vacia";
    else
    {
        actual = primero;
        int i=1;
        while(actual != NULL)
        {
            s<<"\t\t["<<i++<<"]-----------------------------\n";
            s<<actual->getInfo()->toString()<<endl;
            actual = actual->getSigNodo();
        }
    }

    return s.str();
}

template<class T>
T* ListaEnlazada<T>::buscar(string codigo){

 actual=primero;
	while(actual!=NULL)
	{
		if(*(actual->getInfo())==codigo)
		{
			return (actual->getInfo());
		}

		actual=actual->getSigNodo();
	}
	return NULL;
}

template<class T>
int ListaEnlazada<T>::getCantidad()
{
	return cantidad;
}


template<class T>
void ListaEnlazada<T>::insertarPos(int pos, T* e) //comienza en 0
{
    if(pos == cantidad+1)
    {
        this->insertarUltimo(e);
    }
    else if(pos==1)
    {
        this->insertarPrimero(e);
    }
    else
    {
        actual = primero;
        NodoSimple<T>* aux = primero;
        for(int i=1;i<pos;i++)
        {
            aux = actual;
            actual = actual->getSigNodo();
        }
        NodoSimple<T>* aux2 = new NodoSimple<T>(actual, e);
        aux->setSigNodo(aux2);
        cantidad++;
    }
}

template<class T>
void ListaEnlazada<T>::eliminarPos(int pos)
{
    if(primero != NULL)
    {

        actual = primero;
        if(pos == cantidad)
        {
            NodoSimple<T>* aux = actual;
            while(actual!=NULL)
            {
                aux = actual;
                actual = actual->getSigNodo();
            }
            delete aux;
            cantidad --;                
        }
        else if(pos==0)
        {
            NodoSimple<T>* aux = actual;
            if(actual->getSigNodo()!=NULL)
                primero = actual->getSigNodo();
            delete aux;
            cantidad--;
        }
        else
        {
            NodoSimple<T>* aux = actual;
            for(int i=1;i<pos;i++)
            {
                aux = actual;
                actual = actual->getSigNodo();
            }
            aux->setSigNodo(actual->getSigNodo());
            delete actual;
            cantidad--;
        }
    }
}

template<class T>
void ListaEnlazada<T>::intercambiar(int posA, int posB)//intrcambiar posA con posB
{
    if(primero != NULL && primero->getSigNodo() != NULL)
    {
        actual = primero;
        for(int i=1;i<posA;i++)
        {
            actual = actual->getSigNodo();
        }
        NodoSimple<T>* A = actual;

        actual = primero;
        for(int i=1;i<posB;i++)
        {
            actual = actual->getSigNodo();
        }
         NodoSimple<T>* B = actual;

        T* aux = A->getInfo();
        A->setInfo(B->getInfo());
        B->setInfo(aux);
        
    }
}
